#ifndef __FILESYS_H__
#define __FILESYS_H__

#include "wx/defs.h"
#include "wx/stream.h"
#include "wx/datetime.h"
#include "wx/filename.h"
#include "wx/hashmap.h"

class wxFSFile;
class wxFileSystemHandler;
class wxFileSystem;

class wxFSFile : public wxObject {
  public:
    wxFSFile( wxInputStream *stream, const wxString& loc, const wxString& mimetype,
              const wxString& anchor, wxDateTime modif ) {
      m_Stream = stream;
      m_Location = loc;
      m_MimeType = mimetype;
      m_MimeType.MakeLower();
      m_Anchor = anchor;
      m_Modif = modif;
    }

    virtual ~wxFSFile() { delete m_Stream; }
    wxInputStream *GetStream() const { return m_Stream; }
    wxInputStream *DetachStream() {
      wxInputStream *stream = m_Stream;
      m_Stream = NULL;
      return stream;
    }

    void SetStream( wxInputStream *stream ) {
      delete m_Stream;
      m_Stream = stream;
    }
    const wxString& GetMimeType() const { return m_MimeType; }
    const wxString& GetLocation() const { return m_Location; }
    const wxString& GetAnchor() const { return m_Anchor; }
    wxDateTime GetModificationTime() const { return m_Modif; }
  private:
    wxInputStream *m_Stream;
    wxString m_Location;
    wxString m_MimeType;
    wxString m_Anchor;
    wxDateTime m_Modif;
    DECLARE_ABSTRACT_CLASS( wxFSFile )
    DECLARE_NO_COPY_CLASS( wxFSFile )
};

class wxFileSystemHandler : public wxObject {
  public:
    wxFileSystemHandler() : wxObject() {}
    virtual bool CanOpen( const wxString& location ) = 0;
    virtual wxFSFile* OpenFile( wxFileSystem& fs, const wxString& location ) = 0;
    virtual wxString FindFirst( const wxString& spec, int flags = 0 );
    virtual wxString FindNext();

  protected:
    wxString GetProtocol( const wxString& location ) const;

    wxString GetLeftLocation( const wxString& location ) const;
    wxString GetAnchor( const wxString& location ) const;
    wxString GetRightLocation( const wxString& location ) const;
    wxString GetMimeTypeFromExt( const wxString& location );

    DECLARE_ABSTRACT_CLASS( wxFileSystemHandler )
};

enum {
  wxFS_READ = 1,      // Open for reading
  wxFS_SEEKABLE = 4   // Returned stream will be seekable
};

WX_DECLARE_VOIDPTR_HASH_MAP_WITH_DECL( wxFileSystemHandler*, wxFSHandlerHash, class );

class wxFileSystem : public wxObject {
  public:
    wxFileSystem() : wxObject() { m_FindFileHandler = NULL;}
    virtual ~wxFileSystem();
    void ChangePathTo( const wxString& location, bool is_dir = false );

    wxString GetPath() const {return m_Path;}
    wxFSFile* OpenFile( const wxString& location, int flags = wxFS_READ );
    wxString FindFirst( const wxString& spec, int flags = 0 );
    wxString FindNext();

    // find a file in a list of directories, returns false if not found
    bool FindFileInPath( wxString *pStr, const wxChar *path, const wxChar *file );

    // Adds FS handler.
    // In fact, this class is only front-end to the FS handlers :-)
    static void AddHandler( wxFileSystemHandler *handler );

    // Removes FS handler
    static wxFileSystemHandler* RemoveHandler( wxFileSystemHandler *handler );

    // Returns true if there is a handler which can open the given location.
    static bool HasHandlerForPath( const wxString& location );

    // remove all items from the m_Handlers list
    static void CleanUpHandlers();

    // Returns the native path for a file URL
    static wxFileName URLToFileName( const wxString& url );

    // Returns the file URL for a native path
    static wxString FileNameToURL( const wxFileName& filename );


  protected:
    wxFileSystemHandler *MakeLocal( wxFileSystemHandler *h );

    wxString m_Path;
    wxString m_LastName;
    // name of last opened file (full path)
    static wxList m_Handlers;
    // list of FS handlers
    wxFileSystemHandler *m_FindFileHandler;
    // handler that succeed in FindFirst query
    wxFSHandlerHash m_LocalHandlers;
    // Handlers local to this instance

    DECLARE_DYNAMIC_CLASS( wxFileSystem )
    DECLARE_NO_COPY_CLASS( wxFileSystem )
};

class wxLocalFSHandler : public wxFileSystemHandler {
  public:
    virtual bool CanOpen( const wxString& location );
    virtual wxFSFile* OpenFile( wxFileSystem& fs, const wxString& location );
    virtual wxString FindFirst( const wxString& spec, int flags = 0 );
    virtual wxString FindNext();
    static void Chroot( const wxString& root ) { ms_root = root; }

  protected:
    static wxString ms_root;
};

#endif
